import { app, BrowserWindow, shell, ipcMain } from "electron";
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import path from "node:path";
import os from "node:os";
import { dirname } from "path";

// 手动定义 __dirname 和 __filename
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// 配置
const CONFIG = {
  MAIN_DIST: path.join(process.env.APP_ROOT || "", "dist-electron"),
  RENDERER_DIST: path.join(process.env.APP_ROOT || "", "dist"),
  VITE_DEV_SERVER_URL: process.env.VITE_DEV_SERVER_URL,
  PRELOAD_PATH: path.join(__dirname, "../preload/index.mjs"),
};
const _windows = new Map<string, BrowserWindow>();
const _windowData = new Map<string, any>();

// 窗口配置接口
interface WindowOptions extends Electron.BrowserWindowConstructorOptions {
  url: string;
  windowId?: string;
  data?: any;
  modal?: boolean;
  parent?: BrowserWindow;
  width?: number;
  height?: number;
}

// 窗口管理类
class WindowManager {
  private static _instance: WindowManager;
  private mainWindow: BrowserWindow | null = null;

  private constructor() {
    // 私有构造函数，防止外部实例化
  }

  static get instance(): WindowManager {
    if (!WindowManager._instance) {
      WindowManager._instance = new WindowManager();
    }
    return WindowManager._instance;
  }

  /**
   * 创建主窗口
   * @returns Promise<void>
   */
  async createMainWindow(): Promise<void> {
    try {
      const windowId = "main-window";

      if (this.mainWindow) {
        console.warn("Main window already exists");
        return;
      }

      this.mainWindow = new BrowserWindow({
        title: "Main window",
        icon: path.join(process.env.VITE_PUBLIC || "", "favicon.ico"),
        width: 1024,
        height: 768,
        webPreferences: {
          preload: CONFIG.PRELOAD_PATH, // 预加载脚本
          nodeIntegration: process.env.VITE_DEV_SERVER_URL ? true : false, // 是否集成 Node.js
          contextIsolation: true, // 上下文隔离
        },
      });

      _windows.set(windowId, this.mainWindow);
      _windowData.set(windowId, {
        type: "main",
        createdAt: new Date().toISOString(),
      });

      if (CONFIG.VITE_DEV_SERVER_URL) {
        await this.mainWindow.loadURL(CONFIG.VITE_DEV_SERVER_URL);
        this.mainWindow.webContents.openDevTools();
      } else {
        await this.mainWindow.loadFile(
          path.join(CONFIG.RENDERER_DIST, "index.html")
        );
      }

      this.setupMainWindowEvents();
    } catch (error) {
      console.error("Failed to create main window:", error);
      throw error;
    }
  }

  /**
   *
   * @returns void
   */
  private setupMainWindowEvents(): void {
    if (!this.mainWindow) return;

    this.mainWindow.on("closed", () => {
      _windows.delete("main-window");
      _windowData.delete("main-window");
      this.mainWindow = null;
    });

    this.mainWindow.webContents.on("did-finish-load", () => {
      this.mainWindow?.webContents.send(
        "main-process-message",
        new Date().toLocaleString()
      );
    });

    // 处理新窗口打开
    this.mainWindow.webContents.setWindowOpenHandler(({ url }) => {
      if (url.startsWith("https:")) shell.openExternal(url);
      return { action: "deny" };
    });
  }

  getMainWindow(): BrowserWindow | null {
    return this.mainWindow;
  }
  /**
   * 创建新窗口
   * @param options 窗口选项
   * @returns Promise<BrowserWindow>
   */
  async createWindow(options: WindowOptions): Promise<BrowserWindow> {
    try {
      const {
        url,
        windowId = `window_${Date.now()}`,
        data,
        modal = false,
        ...restOptions
      } = options;

      if (_windows.has(windowId)) {
        throw new Error(`Window with id ${windowId} already exists`);
      }

      // For modal windows, if parent is not specified, use the main window
      let parent = options.parent;
      if (modal && !parent) {
        parent = this.getMainWindow();
        if (!parent) {
          throw new Error("Cannot create modal window without a parent window");
        }
      }

      const defaultOptions: Electron.BrowserWindowConstructorOptions = {
        width: options.width || 800,
        height: options.height || 600,
        parent: parent,
        modal: modal,
        webPreferences: {
          nodeIntegration: false,
          contextIsolation: true,
          preload: CONFIG.PRELOAD_PATH,
        },
      };

      const win = new BrowserWindow({
        ...defaultOptions,
        ...restOptions,
      });

      if (data) {
        _windowData.set(windowId, data);
      }

      _windows.set(windowId, win);

      try {
        if (CONFIG.VITE_DEV_SERVER_URL) {
          await win.loadURL(`${CONFIG.VITE_DEV_SERVER_URL}#${url}`);
          win.webContents.openDevTools();
        } else {
          await win.loadFile(path.join(CONFIG.RENDERER_DIST, url));
        }
      } catch (error) {
        _windows.delete(windowId);
        _windowData.delete(windowId);
        throw error;
      }

      win.on("closed", () => {
        _windows.delete(windowId);
        _windowData.delete(windowId);
      });

      return win;
    } catch (error) {
      console.error("Failed to create window:", error);
      throw error;
    }
  }

  getWindow(windowId: string): BrowserWindow | undefined {
    return _windows.get(windowId);
  }

  getWindowData(windowId: string): any | undefined {
    return _windowData.get(windowId);
  }

  getAllWindows(): Map<string, BrowserWindow> {
    return new Map(_windows);
  }

  // 向指定窗口发送消息
  sendMessageToWindow(windowId: string, channel: string, ...args: any[]): void {
    const win = _windows.get(windowId);
    if (win && !win.isDestroyed()) {
      win.webContents.send(channel, ...args);
    }
  }

  // 广播消息给所有窗口
  broadcastMessage(channel: string, ...args: any[]): void {
    _windows.forEach((win) => {
      if (!win.isDestroyed()) {
        win.webContents.send(channel, ...args);
      }
    });
  }

  // 关闭窗口
  closeWindow(windowId: string): void {
    const win = _windows.get(windowId);
    if (win && !win.isDestroyed()) {
      win.close();
    }
  }
}

// IPC通信管理类
class IPCManager {
  private static _instance: IPCManager;
  private windowManager: WindowManager;

  private constructor() {
    this.windowManager = WindowManager.instance;
    this.setupHandlers();
  }

  static get instance(): IPCManager {
    if (!IPCManager._instance) {
      IPCManager._instance = new IPCManager();
    }
    return IPCManager._instance;
  }

  private setupHandlers() {
    // 处理同步消息
    ipcMain.on("message", (event, arg) => {
      console.log("收到渲染进程消息:", arg);
      event.reply("message-reply", `主进程已收到消息: ${arg}`);
    });

    // 处理异步消息
    ipcMain.handle("async-message", async (event, arg) => {
      console.log("收到渲染进程异步消息:", arg);
      return {
        status: "success",
        message: `主进程已处理异步消息: ${arg}`,
        timestamp: new Date().toISOString(),
      };
    });

    // 处理新窗口打开
    ipcMain.handle("open-win", (_, arg) => {
      const childWindow = new BrowserWindow({
        webPreferences: {
          preload: CONFIG.PRELOAD_PATH,
          nodeIntegration: true,
          contextIsolation: false,
        },
      });

      if (CONFIG.VITE_DEV_SERVER_URL) {
        childWindow.loadURL(`${CONFIG.VITE_DEV_SERVER_URL}#${arg}`);
      } else {
        childWindow.loadFile(path.join(CONFIG.RENDERER_DIST, "index.html"), {
          hash: arg,
        });
      }
    });

    // 处理窗口创建请求
    ipcMain.handle("window-create", async (_, options) => {
      try {
        const win = await this.windowManager.createWindow(options);
        return {
          success: true,
          windowId: options.windowId,
        };
      } catch (error) {
        return {
          success: false,
          error: error instanceof Error ? error.message : "创建窗口失败",
        };
      }
    });

    // 处理获取初始数据请求
    ipcMain.handle("window:get-initial-data", async (event) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (!win) {
        console.log("未找到窗口实例");
        return null;
      }

      // 查找该窗口的 windowId
      let windowId: string | undefined;
      for (const [id, window] of this.windowManager.getAllWindows()) {
        if (window === win) {
          windowId = id;
          break;
        }
      }
      if (windowId) {
        const data = this.windowManager.getWindowData(windowId);
        return data;
      }
      return null;
    });

    // 关闭窗口
    ipcMain.handle("window:close", (_, windowId: string) => {
      try {
        this.windowManager.closeWindow(windowId);
        _windows.delete(windowId);
        _windowData.delete(windowId);
        return { success: true };
      } catch (error) {
        console.error("关闭窗口失败:", error);
        return { success: false, error: error.message };
      }
    });

    // 获取窗口信息
    ipcMain.handle("window:get", (_, windowId: string) => {
      try {
        const win = this.windowManager.getWindow(windowId);
        if (!win) {
          return { success: false, error: "窗口不存在" };
        }
        const bounds = win.getBounds();
        return {
          success: true,
          data: {
            id: windowId,
            ...bounds,
            isMaximized: win.isMaximized(),
            isMinimized: win.isMinimized(),
            isVisible: win.isVisible(),
          },
        };
      } catch (error) {
        console.error("获取窗口信息失败:", error);
        return { success: false, error: error.message };
      }
    });

    // 向指定窗口发送消息
    ipcMain.handle(
      "window:send-message",
      (_, windowId: string, channel: string, ...args: any[]) => {
        try {
          this.windowManager.sendMessageToWindow(windowId, channel, ...args);
          return { success: true };
        } catch (error) {
          console.error("发送消息失败:", error);
          return { success: false, error: error.message };
        }
      }
    );

    // 广播消息给所有窗口
    ipcMain.handle(
      "window:broadcast-message",
      (_, channel: string, ...args: any[]) => {
        try {
          this.windowManager.broadcastMessage(channel, ...args);
          return { success: true };
        } catch (error) {
          console.error("广播消息失败:", error);
          return { success: false, error: error.message };
        }
      }
    );
  }
}

// 应用初始化
const initApp = async () => {
  if (!app.requestSingleInstanceLock()) {
    app.quit();
    process.exit(0);
  }

  if (os.release().startsWith("6.1")) app.disableHardwareAcceleration();
  if (process.platform === "win32") app.setAppUserModelId(app.getName());

  // 初始化IPC管理器
  IPCManager.instance;

  app.whenReady().then(() => {
    WindowManager.instance.createMainWindow();
  });

  app.on("window-all-closed", () => {
    if (process.platform !== "darwin") {
      app.quit();
    }
  });

  app.on("activate", () => {
    if (!WindowManager.instance.getMainWindow()) {
      WindowManager.instance.createMainWindow();
    }
  });

  app.on("second-instance", () => {
    if (WindowManager.instance.getMainWindow()) {
      // Focus on the main window if the user tried to open another
      if (WindowManager.instance.getMainWindow().isMinimized())
        WindowManager.instance.getMainWindow().restore();
      WindowManager.instance.getMainWindow().focus();
    }
  });
};

// 启动应用
initApp();
